/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include "../Widget.h"
#include "事件处理.h"


static float64 gdur;
static clock_t g时间start = clock();
static clock_t g时间end;


static uint8 g键盘以按下键[4] = {};

static std::set<S_键位映射*>	g_结束执行键位映射;
static std::set<S_键位映射*>	g_待移除键位映射;





Inline bool f_键位执行准备(S_键位映射* km) {
	switch (km->状态) {
		case E_键位执行状态::e_准备:
			km->状态 = E_键位执行状态::e_开始;
			g_结束执行键位映射.insert(km);
			return true;
		case E_键位执行状态::e_开始:
			km->状态 = E_键位执行状态::e_执行;
			return true;
		case E_键位执行状态::e_执行:
			return true;
		default:
			break;
	}
	return false;
}

Inline bool f_键位缓存准备(S_键位映射* km, const C_Widget* w) {
	static C_Widget* 当前执行拖放组件 = nullptr;

	switch (km->状态) {
		case E_键位执行状态::e_准备:
			return true;
		case E_键位执行状态::e_开始:
			
			g_结束执行键位映射.insert(km);
			return true;
		case E_键位执行状态::e_执行:
			return true;
		default:
			break;
	}
	return false;
}

Inline bool f_键位执行结束(S_键位映射* km) {
	if (km->状态 >= E_键位执行状态::e_完成) {
		km->状态 = E_键位执行状态::e_准备;
		//g_结束执行键位映射.erase(km);
		g_待移除键位映射.insert(km);
		return true;
	}
	return false;
}




static bool f_执行键盘事件(S_键盘键位映射* mk, const uint8* 键盘按键状态, C_Widget* 当前组件) {
	static C_Widget* 当前执行拖放组件 = nullptr;
	uint8 bit = 0;

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}
		}
		else {
			if (g键盘以按下键[k]) {
				mk->记录 |= 1 << k;
			}
		}
	}

	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}

		//if (键盘按键状态[mk->键盘按键[k]] == DEF_按键状态_准备 && mk->状态 == E_键位执行状态::e_准备) {
		//	当前执行拖放组件 = 当前组件;
		//	return false;
		//}
	}

	if (bit && mk->记录 == bit) {
		mk->记录 = 0;

		switch (mk->状态) {
			case E_键位执行状态::e_准备: mk->状态 = E_键位执行状态::e_开始; break;
			case E_键位执行状态::e_开始: mk->状态 = E_键位执行状态::e_执行; break;
		}

		return true;
	}

	if (mk->状态 == E_键位执行状态::e_执行) {
		mk->状态 = E_键位执行状态::e_完成;
		mk->记录 = 0;
		当前执行拖放组件 = nullptr;
		return true;
	}

	if (控制键全部释放) {
		mk->状态 = E_键位执行状态::e_准备;
		mk->记录 = 0;
		当前执行拖放组件 = nullptr;
	}
	return false;
}

bool f_event_执行鼠标事件(S_鼠标键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态) {
	uint8 bit = 0;
	mk->记录 = 0;

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}
		}

		if (mk->鼠标状态[k]) {
			bit |= 1 << k + 4;

			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
				mk->记录 |= 1 << k + 4;
			}
		}
	}

	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
	}

	if (bit && mk->记录 == bit) {
		mk->记录 = 0;
		return true;
	}

	if (控制键全部释放) {
		mk->记录 = 0;
	}
	return false;
}

static bool f_执行拖放事件(S_拖拽键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态, uint32 键盘按下数量) {

	uint8 按下数量 = 0;
	uint8 bit = 0;
	mk->记录 = 0;

	switch (mk->拖放状态)
	{
	case E_拖放状态::e_拖放_开始: {
		mk->拖放状态 = E_拖放状态::e_拖放_进行;
		break;
	}
	case E_拖放状态::e_拖放_进行: {
		break;
	}
	case E_拖放状态::e_拖放_结束: {
		break;
	}
	default:
		break;
	}

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}

			++按下数量;
		}
		//cout << "mk->鼠标按键[k] = " << mk->鼠标按键[k] << endl;
		if (mk->鼠标状态[k]) {
			bit |= 1 << k + 4;

			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
				mk->记录 |= 1 << k + 4;
			}
		}
	}


	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
	}


	if (按下数量 == 键盘按下数量 && mk->记录 == bit) {
		//mk->状态 = 0;
		return true;
	}

	if (控制键全部释放) {
		//mk->状态 = 0;
		mk->记录 = 0;
	}

	return false;
}

static bool f_执行拖拽事件(S_拖拽键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态, uint32 键盘按下数量, C_Widget* 当前组件) {
	static C_Widget* 当前执行拖放组件 = nullptr;

	uint8 按下数量 = 0;
	uint8 bit = 0;
	mk->记录 = 0;

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
				++按下数量;
			}
		}

		if (mk->鼠标状态[k]) {
			bit |= 1 << (k + 4);
			//std::cout << "mk->鼠标按键[k] = " << int32(mk->鼠标状态[k]) << " = " << int32(鼠标按键状态[mk->鼠标按键[k]]) << std::endl;
			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
				mk->记录 |= 1 << (k + 4);
			}
		}
	}


	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
		if (鼠标按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}

		if (鼠标按键状态[mk->鼠标按键[k]] == DEF_按键状态_按下 && mk->状态 == E_键位执行状态::e_准备) {
			当前执行拖放组件 = 当前组件;
			return false;
		}
	}

	//std::cout << "mk->鼠标按键[k] = " << int32(bit) << " " << int32(mk->记录) << " " << int32(按下数量) << " " << 键盘按下数量 << std::endl;
	if (按下数量 == 键盘按下数量 && mk->记录 == bit && 当前执行拖放组件 == 当前组件) {
		switch (mk->状态) {
			case E_键位执行状态::e_准备: mk->状态 = E_键位执行状态::e_开始; break;
			case E_键位执行状态::e_开始: mk->状态 = E_键位执行状态::e_执行; break;
		}
		return true;
	}
	if (mk->状态 == E_键位执行状态::e_执行) {
		mk->状态 = E_键位执行状态::e_完成;
		当前执行拖放组件 = nullptr;
		return true;
	}

	if (控制键全部释放) {
		mk->记录 = 0;
		mk->状态 = E_键位执行状态::e_准备;
		当前执行拖放组件 = nullptr;
	}

	return false;
}


bool f_键盘单个按键状态(const uint8* 键盘按键状态, uint8 key, uint8 状态) {
	return (键盘按键状态[key] & 状态);
}



bool f_执行双击事件(S_鼠标双击键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态) {
	uint8 bit = 0;
	mk->记录 = 0;

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}
		}

		if (mk->鼠标状态[k]) {
			bit |= 1 << k + 4;

			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
				mk->记录 |= 1 << k + 4;
			}
		}
	}

	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
	}

	if (bit && mk->记录 == bit) {
		mk->记录 = 0;

		if (mk->开始计时 && !mk->结束计时) {
			mk->结束计时 = clock();
			auto gdur = (double)(mk->结束计时 - mk->开始计时);
			if (gdur > S_UI主题::ui_双击时间间隔) {
				mk->开始计时 = 0;
			}
			else {
				mk->开始计时 = 0;
				mk->结束计时 = 0;
				return true;
			}
		}
		else {
			mk->开始计时 = clock();
		}
	}

	if (控制键全部释放) {
		mk->记录 = 0;
		
		mk->结束计时 = clock();
		auto gdur = (double)(mk->结束计时 - mk->开始计时);
		if (gdur > S_UI主题::ui_双击时间间隔) {
			mk->开始计时 = 0;
		}
		mk->结束计时 = 0;
	}
	return false;
}




bool f_event_执行键位绑定事件(C_Widget& w, C_Widget管理& gm, const S_输入环境& input, uint32 键盘按下数量) {
	uint32 键位映射num = w.m_键位映射.size();
	auto* 键位映射keys = w.m_键位映射.data();

	for (uint8 i = 0; i < 键位映射num; ++i) {
		switch (键位映射keys[i]->m_Type) {
			
			case E_键位映射类型::e_键映射类型_鼠标: {
				S_鼠标键位映射* km = (S_鼠标键位映射*)键位映射keys[i];
				if ( f_event_执行鼠标事件(km, input.m_Key.Keys状态, gm.鼠标按键状态) && f_键位执行准备(键位映射keys[i]) ) {
					if (!(km->发生组件)) km->发生组件 = &w;
					if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
						continue;
					}
					return true;
				}
				break;
			}
			
			case E_键位映射类型::e_键映射类型_拖放: {
				S_拖拽键位映射* km = (S_拖拽键位映射*)键位映射keys[i];
				if (((S_鼠标属性*)input.m_鼠标)->lX || ((S_鼠标属性*)input.m_鼠标)->lY) {
					if ( f_执行拖放事件(km, input.m_Key.Keys状态, gm.鼠标按键状态, 键盘按下数量) && f_键位执行准备(键位映射keys[i]) ) {
						if (!(km->发生组件)) km->发生组件 = &w;
						if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
							continue;
						}
						return true;
					}
				}
				break;
			}
			case E_键位映射类型::e_键映射类型_双击: {
				S_鼠标双击键位映射* km = (S_鼠标双击键位映射*)键位映射keys[i];
				if ( f_执行双击事件(km, input.m_Key.Keys状态, gm.鼠标按键状态) && f_键位执行准备(键位映射keys[i]) ) {
					if (!(km->发生组件)) km->发生组件 = &w;
					if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
						continue;
					}
					return true;
				}
				break;
			}
			
		}
	}
	return false;
}

bool f_event_执行拖拽事件(C_Widget& w, C_Widget管理& gm, const S_输入环境& input, uint32 键盘按下数量) {
	uint32 键位映射num = w.m_键位映射.size();
	auto* 键位映射keys = w.m_键位映射.data();

	for (uint8 i = 0; i < 键位映射num; ++i) {
		switch (键位映射keys[i]->m_Type) {
			case E_键位映射类型::e_键映射类型_拖拽: {
				S_拖拽键位映射* km = (S_拖拽键位映射*)键位映射keys[i];
				
				if ( f_执行拖拽事件(km, input.m_Key.Keys状态, gm.鼠标按键状态, 键盘按下数量, &w) ) {
					
					if ( ((S_鼠标属性*)input.m_鼠标)->lX || ((S_鼠标属性*)input.m_鼠标)->lY ) {
						//if(km->状态 == E_键位执行状态::e_开始) {
						//	当前执行拖放组件 = &w;
						//}
						//else {
						//	if (当前执行拖放组件 != &w) {
						//		continue;
						//	}
						//}
					}
					else {
						if(km->状态 == E_键位执行状态::e_开始) {
							km->状态 = E_键位执行状态::e_准备;
							continue;
						}
						if(km->状态 == E_键位执行状态::e_执行) {
							continue;
						}
					}
				
					
				
					if (!(km->发生组件)) km->发生组件 = &w;
					auto 传递 = km->event(km->发生组件, km->状态);
				
					if (km->状态 == E_键位执行状态::e_完成) {
						km->状态 = E_键位执行状态::e_准备;
						//当前执行拖放组件 = nullptr;
					}
					if (传递 == E_事件是否传递::e_事件传递_继续) {
						continue;
					}
					return true;
				}
				break;
			}
			case E_键位映射类型::e_键映射类型_键盘: {
				S_键盘键位映射* km = (S_键盘键位映射*)键位映射keys[i];
				if ( f_执行键盘事件(km, input.m_Key.Keys状态, &w) ) {
					if (!(km->发生组件)) km->发生组件 = &w;

					//static std::vector<S_键盘键位映射*> 当前执行事件键位;
					auto 传递 = km->event(km->发生组件, km->状态);

					if (km->状态 == E_键位执行状态::e_完成) {
						km->状态 = E_键位执行状态::e_准备;
					}
					else {
						f_键位缓存准备(键位映射keys[i], km->发生组件);
					}
					if (传递 == E_事件是否传递::e_事件传递_继续 || km->状态 == E_键位执行状态::e_执行) {
						continue;
					}
					return true;
				}
				break;
			}
		}
		
	}
	return false;
}

bool f_event_执行事件结束(C_Widget管理& gm, const S_输入环境& input, uint32 键盘按下数量) {
	for (auto& e : g_结束执行键位映射) {
		switch (e->m_Type) {
			case E_键位映射类型::e_键映射类型_键盘: {
				S_键盘键位映射* km = (S_键盘键位映射*)e;
				if ( f_执行键盘事件(km, input.m_Key.Keys状态, km->发生组件) && f_键位执行结束(e) ) {
					if (km->event(km->发生组件, E_键位执行状态::e_完成) == E_事件是否传递::e_事件传递_继续) {
					}
				}
				break;
			}
			case E_键位映射类型::e_键映射类型_鼠标: {
				S_鼠标键位映射* km = (S_鼠标键位映射*)e;
				if ( f_event_执行鼠标事件(km, input.m_Key.Keys状态, gm.鼠标按键状态) && f_键位执行结束(e) ) {
					if (km->event(km->发生组件, E_键位执行状态::e_完成) == E_事件是否传递::e_事件传递_继续) {
					}
				}
				break;
			}
			case E_键位映射类型::e_键映射类型_拖放: {
				S_拖拽键位映射* km = (S_拖拽键位映射*)e;
				if ( f_执行拖放事件(km, input.m_Key.Keys状态, gm.鼠标按键状态, 键盘按下数量) && f_键位执行结束(e) ) {
					if (km->event(km->发生组件, E_键位执行状态::e_完成) == E_事件是否传递::e_事件传递_继续) {
					}
				}
				break;
			}
			case E_键位映射类型::e_键映射类型_双击: {
				S_鼠标双击键位映射* km = (S_鼠标双击键位映射*)e;
				if ( f_执行双击事件(km, input.m_Key.Keys状态, gm.鼠标按键状态) && f_键位执行结束(e) ) {
					if (km->event(km->发生组件, E_键位执行状态::e_完成) == E_事件是否传递::e_事件传递_继续) {
					}
				}
				break;
			}
		}
	}

	for (auto& e : g_待移除键位映射) {
		g_结束执行键位映射.erase(e);
	}
	g_待移除键位映射.clear();
	return false;
}













